package client

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"net/http"
	"time"
	"xiaoniu-job/internal/config"
	"xiaoniu-job/internal/db"
	"xiaoniu-job/pkg"
	"xiaoniu-job/pkg/util"
)

/**
每一个任务执行都会生成一个唯一的taskId,这个taskId非常重要
*/

// SendTask 向对应的执行器发送执行任务的请求
func SendTask(taskId uint64, taskLabel string, executorAddr string, taskParam string) (string, error) {
	if executorAddr == "" {
		return "调度失败", errors.New("执行器地址不能为空！")
	}
	if taskLabel == "" {
		return "调度失败", errors.New("任务标识不能为空！")
	}
	if taskId == 0 {
		return "调度失败", errors.New("任务Id不符合要求！")
	}

	var bodyMap = make(map[string]interface{})
	bodyMap["taskId"] = taskId
	bodyMap["taskLabel"] = taskLabel
	bodyMap["taskParam"] = taskParam
	bodyMap["logCallBackUrl"] = config.ServerRation.AppIp + "/api/client/callBack"

	response, err := util.PostJson(executorAddr+"/run", bodyMap)
	if err != nil {
		return "调度失败", err
	}
	if response.Code == 0 {
		return "调度成功", nil
	}
	return "调度失败", errors.New(response.Msg)
}

// GetLog 向对应的执行器发送请求获取日志
func GetLog(taskId int64, executorAddr string) (bool, error) {
	if executorAddr == "" {
		return false, errors.New("执行器地址不能为空！")
	}
	if taskId == 0 {
		return false, errors.New("任务Id不符合要求！")
	}

	var bodyMap = make(map[string]interface{})
	bodyMap["taskId"] = taskId

	response, err := util.PostJson(executorAddr+"/getLog", bodyMap)
	if err != nil {
		return false, err
	}
	if response.Code == 0 {
		return true, nil
	}
	return false, errors.New(response.Msg)
}

// QueryLocalLog 向对应的执行器发送请求获取任务在执行时的本地日志
func QueryLocalLog(taskId uint64, executorAddr string) (interface{}, error) {
	if executorAddr == "" {
		return nil, errors.New("执行器地址不能为空！")
	}
	if taskId == 0 {
		return nil, errors.New("任务Id不符合要求！")
	}

	var bodyMap = make(map[string]interface{})
	bodyMap["taskId"] = taskId

	response, err := util.PostJson(executorAddr+"/queryLocalLog", bodyMap)
	if err != nil {
		return nil, err
	}
	if response.Code == 0 {
		return response.Data, nil
	}
	return nil, errors.New(response.Msg)
}

// CallBackHandler 客户端回调服务端的接口
func CallBackHandler(w http.ResponseWriter, r *http.Request) {
	res, err := ioutil.ReadAll(r.Body)
	if err != nil {
		var response = pkg.NewFailResponse("参数有误")
		marshal, _ := json.Marshal(response)
		w.Write(marshal)
		return
	}
	var entity pkg.ClientResponse
	err = json.Unmarshal(res, &entity)
	if err != nil {
		var response = pkg.NewFailResponse("JSON转换异常")
		marshal, _ := json.Marshal(response)
		w.Write(marshal)
		return
	}
	// 将执行结果保存到数据库
	now, err := time.ParseInLocation(`"2006-01-02 15:04:05"`, entity.TaskResult.FinishTime, time.Local)
	if err != nil {
		var response = pkg.NewFailResponse("不合法的时间")
		marshal, _ := json.Marshal(response)
		w.Write(marshal)
		return
	}
	cnt, err := db.UpdateJobLogResultByTaskId(entity.TaskId, now, entity.TaskResult.Result)
	if cnt > 0 {
		var response = pkg.NewSuccessResponse("保存成功")
		marshal, _ := json.Marshal(response)
		w.Write(marshal)
	} else {
		var response = pkg.NewFailResponse("执行结果保存出错：" + err.Error())
		marshal, _ := json.Marshal(response)
		w.Write(marshal)
	}
}

// QueryLogHandler 查询客户端本地的执行日志
func QueryLogHandler(w http.ResponseWriter, r *http.Request) {
	res, err := ioutil.ReadAll(r.Body)
	if err != nil {
		w.Write([]byte("参数有误"))
		return
	}
	var entity pkg.JobLog
	err = json.Unmarshal(res, &entity)
	if err != nil {
		w.Write([]byte("JSON转换异常"))
		return
	}

	jobLog, err := db.GetJobLogById(entity.Id)
	if err != nil {
		w.Write([]byte("查询失败" + err.Error()))
		return
	} else {
		localLog, e := QueryLocalLog(jobLog.Id, jobLog.ExecutorAddress)
		if e != nil {
			w.Write([]byte(e.Error()))
		} else {
			w.Write([]byte(localLog.(string)))
		}
	}
}

// HeartBeatHandler 接收客户端的心跳请求
func HeartBeatHandler(w http.ResponseWriter, r *http.Request) {
	res, err := ioutil.ReadAll(r.Body)
	if err != nil {
		var response = pkg.NewFailResponse("参数有误")
		marshal, _ := json.Marshal(response)
		w.Write(marshal)
		return
	}
	var entity pkg.HeartBeatRequest
	err = json.Unmarshal(res, &entity)
	if err != nil {
		var response = pkg.NewFailResponse("JSON转换异常")
		marshal, _ := json.Marshal(response)
		w.Write(marshal)
		return
	}

	_, err = db.SaveExecutor(&entity)
	if err != nil {
		var response = pkg.NewFailResponse("失败：" + err.Error())
		marshal, _ := json.Marshal(response)
		w.Write(marshal)
	} else {
		var response = pkg.NewSuccessResponse("成功")
		marshal, _ := json.Marshal(response)
		w.Write(marshal)
	}
}
